package com.september.concurrent;

import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Semaphore;

import com.google.code.morphia.Datastore;
import com.september.mongo.data.DataProvider;
import com.september.mongo.entities.City;
import com.september.mongo.entities.Nation;
import com.september.mongo.entities.Province;
import com.september.mongo.entities.Region;
import com.september.prop.Properteer;
import com.september.util.BaseData;

public class DupsHandlerRecThread<T extends BaseData, K extends BaseData> extends Thread implements IThread{

	private Semaphore semaphore;
	private Semaphore innerSemaphore = new Semaphore(2,true);
	private List<T> entityList;
	
	private Class<K> expectedReturn;
	private String reference;

	private String identifier = this.getClass().getName()+"\t"+this.getId();

	
	public  DupsHandlerRecThread(List<T> entityList, Class<K> expectedReturn ,Semaphore sem, String reference) {

		this.semaphore = sem;
		this.entityList = entityList;
		this.expectedReturn = expectedReturn;
		this.reference = reference;
	}

	public void run() {
		try {
			semaphore.acquire();
			criticalCode();
			semaphore.release();
		} catch (InterruptedException e) {
			Properteer.getInstance().getLogger(DupsHandlerRecThread.class).error(e.getClass().getName(), e);
		} catch (UnknownHostException e) {
			Properteer.getInstance().getLogger(DupsHandlerRecThread.class).error(e.getClass().getName(), e);
		}

	}

	public void handleDups(List<City> cityList, Datastore ds) {
		if (cityList.size() == 0)
			return;
		List<String> reference = new LinkedList<String>();
		for (City city : cityList) {
			if (reference.contains(city.getName())) {
				ds.delete(city);
				Properteer.getInstance().getLogger(DupsHandlerRecThread.class).debug("Deleting " + city.getName() + "\t from "
						+ city.getProvince().getCode() + "\t"
						+ city.getRegion().getCode() + "\t"
						+ city.getNation().getCountry());
			} else {
				reference.add(city.getName());
			}
		}
	}

	private void criticalCode() throws UnknownHostException {

		Datastore ds = (new DataProvider()).getDatastore();
		
		try {
			log(identifier+"\tstarted");
			for (T entity : entityList) {
				
				//ds.find(Province).field
				List<K> innerList = (List<K>) ds.find(expectedReturn).field(reference)
						.equal(entity).asList();
				
				log(identifier+"\tfound "+innerList.size()+"\tchildren of "+entity.getClass().getName());
				
				if(entity.getClass().equals(Nation.class)) {
					(new DupsHandlerRecThread(innerList, Province.class, innerSemaphore, "region")).start();
				}
				else if (entity.getClass().equals(Region.class)) {
					(new DupsHandlerRecThread(innerList, City.class, innerSemaphore, "province")).start();
				}
				
				else if (entity.getClass().equals(Province.class)) {
					handleDups((List<City>) innerList, ds);
				}
				
				
				//(new CityDupsHandlerThread(cityList, citySem)).start();
				
			}

		}

		catch (Exception e) {
			e.printStackTrace();
		}
		
		
		log(identifier+"\tstarted");
		//handleDups(entityList, ds);
	

	}
	
	public void log(String message) {
		Properteer.getInstance().getLogger(DupsHandlerRecThread.class).debug(message);
	}

}
